package monitor

import (
	"cloud_worm/worm/client/monitor/fileevent"
	"context"
	"fmt"
	"cloud_worm/worm/config"
	"strings"
	"github.com/golang/glog"
	"errors"
	"io/ioutil"
	"sync"
	"cloud_worm/worm/client/monitor/monitorlog"
	"cloud_worm/util/ufile"
	"cloud_worm/util/proto/ujson"
)

var fileMutex   sync.Mutex
var fileMonitor *fileevent.FileMonitor

// StartFileMonitor file monitor
func StartFileMonitor(localIP string) error {
	fileMutex.Lock()
	defer fileMutex.Unlock()

	if fileMonitor != nil {
		return errors.New("file monitor had started")
	}

	if strings.Contains(config.CfgInst.RunMode, "dev") {
		// 测试环境
		ctxFile, cancelFile := context.WithCancel(context.Background())

		// 测试环境，文件变更写日志，不写kafka
		fs := fileevent.NewFileMonitor(localIP, nil, monitorlog.MonLogFd, cancelFile)
		if fs == nil {
			e := errors.New("new file monitor failed")
			PushMonitorErrInfo(e)
			return e
		}
		fs.Loop(ctxFile)

		fileMonitor = fs
	} else if strings.HasPrefix(localIP, "10.70.") == false && strings.HasPrefix(localIP, "10.13.") == false {
		// 线上环境，但是不包括"10.13."和"10.90"
		ctxFile, cancelFile := context.WithCancel(context.Background())

		// 文件变更，写日志、写kafka
		p, err := producerPool.Get(CmdTopic)
		if err != nil {
			e := fmt.Errorf("get topic'%s' producer error", CmdTopic)
			PushMonitorErrInfo(e)
			return e
		}
		fs := fileevent.NewFileMonitor(localIP, p, monitorlog.MonLogFd, cancelFile)
		if fs == nil {
			producerPool.Put(CmdTopic)
			e := errors.New("new file monitor failed")
			PushMonitorErrInfo(e)
			return e
		}
		fs.Loop(ctxFile)

		fileMonitor = fs
	}

	fileURL := fmt.Sprintf("%s/worm/worm/%s",
		config.CfgInst.StartConfig.(*config.ClientConfig).ServerSet.AutoConfigURL, ujson.FileRuleFile)
	if err := updateFileRuleWithoutLock(fileURL, "init"); err != nil {
		glog.Errorf("updateFileRuleWithoutLock: %s", err.Error())
		PushMonitorErrInfo(err)
	}
	glog.Info("start file monitor loop.....")
	return nil
}

func StopFileMonitor()  {
	fileMutex.Lock()
	defer fileMutex.Unlock()

	if fileMonitor == nil {
		return
	}

	producerPool.Put(CmdTopic)
	fileMonitor.Close()
	fileMonitor = nil
}

func init()  {
	fileMonitor = nil
}


func UpdateFileRule(fileURL string, md5 string) error {
	fileMutex.Lock()
	defer fileMutex.Unlock()

	if fileMonitor == nil {
		return nil
	}

	destFile := "./var/" + ujson.FileRuleFile
	oldMd5 := ufile.GetFileMd5(destFile)
	if oldMd5 == md5 {
		return nil
	}

	if err := ufile.DownloadFile(fileURL, destFile); err != nil {
		glog.Error(fmt.Sprintf("download file'%s' error: %s", ujson.FileRuleFile, err.Error()))
		PushMonitorErrInfo(err)
		return err
	}

	data, err := ioutil.ReadFile(destFile)
	if err != nil {
		return err
	}
	if strings.Contains(string(data), ujson.Page404NotFound) {
		e := errors.New(fmt.Sprintf("url: %s, 404 page not found", fileURL))
		PushMonitorErrInfo(e)
		return e
	}
	tmp := strings.Split(string(data), "\n")

	fileList := make(map[string][]string, len(tmp))
	for _, item := range tmp {

		f := strings.Split(item, "|")
		if len(f) == 2 {
			fileName := strings.TrimSpace(f[0])
			var ignoreList []string
			for _, o := range strings.Split(f[1], ",") {
				o = strings.TrimSpace(o)
				if len(o) <= 0 {
					continue
				}

				ignoreList = append(ignoreList, o)
			}
			fileList[fileName] = ignoreList
		}
	}
	// 加入缺省的wolagent，TODO：暂时不加入wolagent自身的监控
	//fileList["/usr/local/worm/agent"] = []string{
	//	fmt.Sprintf("%d/var", config.CfgInst.Version),
	//}

	if fileMonitor != nil {
		glog.Info(fileList)
		fileMonitor.UpdateFileRule(fileList)
	}
	return nil
}


func updateFileRuleWithoutLock(fileURL string, md5 string) error {
	if fileMonitor == nil {
		return nil
	}

	destFile := "./var/" + ujson.FileRuleFile
	oldMd5 := ufile.GetFileMd5(destFile)
	if oldMd5 == md5 {
		return nil
	}

	if err := ufile.DownloadFile(fileURL, destFile); err != nil {
		glog.Error(fmt.Sprintf("download file'%s' error: %s", ujson.FileRuleFile, err.Error()))
		PushMonitorErrInfo(err)
		return err
	}

	data, err := ioutil.ReadFile(destFile)
	if err != nil {
		return err
	}
	if strings.Contains(string(data), ujson.Page404NotFound) {
		e := errors.New(fmt.Sprintf("url: %s, 404 page not found", fileURL))
		PushMonitorErrInfo(e)
		return e
	}
	tmp := strings.Split(string(data), "\n")

	fileList := make(map[string][]string, len(tmp))
	for _, item := range tmp {

		f := strings.Split(item, "|")
		if len(f) == 2 {
			fileName := strings.TrimSpace(f[0])
			var ignoreList []string
			for _, o := range strings.Split(f[1], ",") {
				o = strings.TrimSpace(o)
				if len(o) <= 0 {
					continue
				}

				ignoreList = append(ignoreList, o)
			}
			fileList[fileName] = ignoreList
		}
	}
	// 加入缺省的wolagent，TODO：暂时不加入wolagent自身的监控
	//fileList["/usr/local/worm/agent"] = []string{
	//	fmt.Sprintf("%d/var", config.CfgInst.Version),
	//}

	if fileMonitor != nil {
		glog.Info(fileList)
		fileMonitor.UpdateFileRule(fileList)
	}
	return nil
}